/**
 * 模块管理器 - 集中动态导入管理
 * 处理 ES 模块的加载和缓存以减少内存开销
 */

class ModuleManager {
  constructor() {
    this._cache = new Map();
    this._loadingPromises = new Map();
  }

  /**
   * 一次性初始化所有常用的 ES 模块
   * @returns {Promise<Object>} 包含所有已加载模块的对象
   */
  async initializeCommonModules() {
    const modules = await Promise.all([
      this.getModule('chalk'),
      this.getModule('ora'),
      this.getModule('inquirer')
    ]);

    return {
      chalk: modules[0],
      ora: modules[1],
      inquirer: modules[2]
    };
  }

  /**
   * 通过名称获取模块，带缓存
   * @param {string} moduleName - 要加载的模块名称
   * @returns {Promise<any>} 已加载的模块
   */
  async getModule(moduleName) {
    // Return from cache if available
    if (this._cache.has(moduleName)) {
      return this._cache.get(moduleName);
    }

    // If already loading, return the existing promise
    if (this._loadingPromises.has(moduleName)) {
      return this._loadingPromises.get(moduleName);
    }

    // Start loading the module
    const loadPromise = this._loadModule(moduleName);
    this._loadingPromises.set(moduleName, loadPromise);

    try {
      const module = await loadPromise;
      this._cache.set(moduleName, module);
      this._loadingPromises.delete(moduleName);
      return module;
    } catch (error) {
      this._loadingPromises.delete(moduleName);
      throw error;
    }
  }

  /**
   * 加载特定模块的内部方法
   * @private
   */
  async _loadModule(moduleName) {
    switch (moduleName) {
      case 'chalk':
        return (await import('chalk')).default;
      case 'ora':
        return (await import('ora')).default;
      case 'inquirer':
        return (await import('inquirer')).default;
      case 'glob':
        return (await import('glob')).glob;
      case 'globSync':
        return (await import('glob')).globSync;
      default:
        throw new Error(`未知模块: ${moduleName}`);
    }
  }

  /**
   * 清除模块缓存以释放内存
   */
  clearCache() {
    this._cache.clear();
    this._loadingPromises.clear();
  }

  /**
   * 一次性获取多个模块
   * @param {string[]} moduleNames - 模块名称数组
   * @returns {Promise<Object>} 以模块名称为键的对象
   */
  async getModules(moduleNames) {
    const modules = await Promise.all(
      moduleNames.map(name => this.getModule(name))
    );

    return moduleNames.reduce((acc, name, index) => {
      acc[name] = modules[index];
      return acc;
    }, {});
  }
}

// Singleton instance
const moduleManager = new ModuleManager();

module.exports = moduleManager;